#include "Encoder.h"


Encoder::Encoder(AVCodecID id, int width, int height)
	:m_codecCtx(NULL)
{
	m_id = id;
	m_width = width;
	m_height = height;
}

Encoder::~Encoder()
{
	if (m_codecCtx)
		avcodec_free_context(&m_codecCtx);
}

int Encoder::encodeVideo(AVPacket * avpkt, const AVFrame * frame, int * got_packet_ptr)
{
	return avcodec_encode_video2(m_codecCtx, avpkt, frame, got_packet_ptr);
}

bool Encoder::open()
{
	m_codec = avcodec_find_decoder(m_id);
	if (!m_codec)
		return false;
	m_codecCtx = avcodec_alloc_context3(m_codec);
	if (!m_codecCtx)
		return false;
	/* put sample parameters */
	//c->bit_rate = 800000;
	/* resolution must be a multiple of two */
	m_codecCtx->width = m_width;
	m_codecCtx->height = m_height;
	/* frames per second */
	m_codecCtx->time_base = { 1, 25 };
	m_codecCtx->gop_size = 10;
	m_codecCtx->max_b_frames = 0;
	m_codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
	m_codecCtx->qmin = 35;
	m_codecCtx->qmax = 65;
	m_codecCtx->thread_count = 1;
	//set private
	//TODO: use AVDictionary to set param
	if (m_codecCtx->codec_id == AV_CODEC_ID_H264)
	{
		av_opt_set(m_codecCtx->priv_data, "preset", "ultrafast", 0);
		av_opt_set(m_codecCtx->priv_data, "tune", "zerolatency", 0);
	}
	if (m_codecCtx->codec_id == AV_CODEC_ID_HEVC)//h265
	{
		av_opt_set(m_codecCtx->priv_data, "x265-params", "qp=20", 0);
		av_opt_set(m_codecCtx->priv_data, "preset", "ultrafast", 0);
		av_opt_set(m_codecCtx->priv_data, "tune", "zero-latency", 0);
	}

	if (avcodec_open2(m_codecCtx, m_codec, NULL) < 0) {
		return false;
	}
	return true;
}
